/***************************************************************************
 *   Copyright (C) 2007 by Warren Kenny   				   *
 *   warren.kenny@gmail.com   						   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
 

template< class T > inline
gsArray<T>::gsArray() :
m_size( 0 ),
m_capacity( 0 ),
m_objects( GS_NULL )
{}


template< class T > inline
gsArray<T>::gsArray( const gsUInt capacity ) :
m_size( 0 ),
m_capacity( capacity ),
m_objects( GS_NULL )
{
	if( m_capacity > 0 )
	{
		m_objects = new T[ m_capacity ];
	}
}


template< class T > inline
gsArray<T>::gsArray( const gsContainer<T>& container ) :
m_size( container.m_size ),
m_capacity( container.m_capacity )
{
	if( m_capacity > 0 )
	{
		m_objects = new T[ m_capacity ];
		for( gsUInt i = 0; i < m_size ; i++ )
		{
			m_objects[i] = container.m_objects[i];
		}
	}
}


template< class T > inline
gsBool gsArray<T>::insert( const T& object )
{
	expand();
	m_objects[m_size++] = object;
	return true;
}


template< class T > inline
gsBool gsArray<T>::remove( const T& object )
{
	gsBool found = false;
	
	for( gsUInt i = 0; i < m_size; i++ )
	{
		if( m_objects[i] == object )
		{
			found = true;
			
			for( gsUInt j = i; j < (m_size-1); j++ )
			{
				m_objects[j] = m_objects[j+1];
			}
			
			m_size--;
		}
	}
	
	return true;
}


template< class T > inline
gsBool gsArray<T>::find( const T& object )
{
	gsBool found = false;
	for( gsUInt i = 0 ; i < m_size ; i++ )
	{
		if( m_objects[i] == object )
		{
			found = true;
			break;
		}
	}
	return found;
}


template< class T > inline
gsBool gsArray<T>::get( const gsUInt index, T& object )
{
	gsBool ok = ( index < m_size );
	if( ok )
	{
		object = m_objects[ index ];
	}
	return ok;
}


template< class T > inline
gsBool gsArray<T>::empty()
{
	return ( m_size == 0 );
}	


template< class T > inline
const gsUInt gsArray<T>::getSize()
{
	return m_size;
}


template< class T > inline
const gsUInt gsArray<T>::getCapacity()
{
	return m_capacity;
}


template< class T > inline
void gsArray<T>::clear()
{
	if( m_objects )
	{
		delete[] m_objects;
		m_objects = GS_NULL;
		m_size = m_capacity = 0;
	}
}


template< class T > inline
void gsArray<T>::setCapacity( const gsUInt newCapacity )
{
	resize( newCapacity );
}


template< class T > inline
T& gsArray<T>::operator[]( const gsUInt arrayIndex ) throw( gsArrayIndexOutOfBoundsException )
{
	if( arrayIndex >= m_size || arrayIndex < 0 )
	{
		gsArrayIndexOutOfBoundsException exception;
		throw( exception );
	}
	else
	{
		return m_objects[ arrayIndex ];
	}
}


template< class T > inline
const T& gsArray<T>::operator[]( const gsUInt arrayIndex ) const throw( gsArrayIndexOutOfBoundsException )
{
	if( arrayIndex >= m_size || arrayIndex < 0 )
	{
		gsArrayIndexOutOfBoundsException exception;
		throw( exception );
	}
	else
	{
		return m_objects[ arrayIndex ];
	}
}


template< class T > inline
T& gsArray<T>::operator=( gsContainer<T> &container )
{
	if( this != &container )
	{
	
		if( container.getSize() > m_capacity )
		{
			resizeNoPreserve( container.getSize() );
		}
	
		gsUInt counter = 0;
		for( gsUInt i = 0 ; i < container.getSize() ; i++ )
		{
			T object;
			if( container.get( i, object ) )
			{
				m_objects[counter] = object;
				counter++;
			}
		}
		m_size = counter;

	}
	return (*this);
}


template< class T > inline
void gsArray<T>::expand()
{
	if( m_size == m_capacity )
	{
		resize( m_capacity + 1 );
	}
}


template< class T > inline
void gsArray<T>::resize( gsUInt newSize )
{
	if( newSize > 0 && newSize != m_capacity )
	{
		T* temp = new T[ newSize ];
		gsUInt copyLimit;
		
		if( newSize > m_size )
		{
			copyLimit = m_size;
		}
		else
		{
			copyLimit = newSize;
		}
		
		if( m_objects )
		{
			for( gsUInt i = 0 ; i < copyLimit ; i++ )
			{
				temp[i] = m_objects[i];
			}
			
			delete[] m_objects;
		}

		m_objects = temp;
		m_capacity = newSize;
		m_size = copyLimit;
	}
}


template< class T > inline
void gsArray<T>::resizeNoPreserve( gsUInt newSize )
{
	if( newSize > 0 && newSize != m_capacity )
	{
		T* temp = new T[ newSize ];
	
		if( m_objects )
		{
			delete[] m_objects;
		}
	
		m_objects = temp;
		m_capacity = newSize;
	}
}


template< class T > inline
gsArray<T>::~gsArray()
{
	clear();
}


	

